package smartbooks.ui.invoices;

import java.awt.Color;
import java.awt.Container;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.DefaultComboBoxModel;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.border.TitledBorder;
import javax.swing.table.DefaultTableModel;
import smartbooks.exceptions.MyException;
import smartbooks.restrictDocuments.JTextFieldMaxLimitDocument;
import smartbooks.ui.SmartBooksUserSettings;
import smartbooks.ui.util.TableCellListener;
import smartbooks.ui.customers.CustomersDialog;
import smartbooks.ui.listeners.CommonMouseListener;
import smartbooks.ui.manager.CustomerManager;
import smartbooks.ui.manager.InvoiceManager;
import smartbooks.ui.manager.ItemManager;
import smartbooks.ui.manager.UserManager;
import smartbooks.ui.manager.UserOrganizationMappingManager;
import smartbooks.ui.util.CommonConstants;
import static smartbooks.ui.util.CommonConstants.CREATE_BUTTON_TEXT;
import static smartbooks.ui.util.CommonConstants.DATE_PATTERN;
import static smartbooks.ui.util.CommonConstants.SAVE_BUTTON_TEXT;
import smartbooks.ui.util.CommonFunctions;
import smartbooksdb.exception.MandatoryFieldException;
import smartbooksdb.hibernatebean.Customer;
import smartbooksdb.hibernatebean.Invoice;
import smartbooksdb.hibernatebean.InvoiceLines;
import smartbooksdb.hibernatebean.Item;

/**
 *
 * @author Ankit
 */
public class InvoicesPanel extends javax.swing.JPanel implements CommonConstants{
    private Invoice editInvoice = null;
    ArrayList states = new ArrayList();
    Map<String, Customer> customersMap = new LinkedHashMap<String, Customer>();
    ArrayList<Item> items = new ArrayList<Item>();
    String[] columnNames = {"No","Qty","Item Name","Item Code","Description","Selling Price","Tax","Total"};
    Invoice invoice = new Invoice();
    ArrayList<InvoiceLines> invoiceLinesList = new ArrayList<InvoiceLines>();
    
    /**
     * Creates new form InvoicesPanel
     * @param editInvoice
     */
    public InvoicesPanel(Invoice editInvoice) {
        if(null!=editInvoice) {
            this.editInvoice = editInvoice;
            this.invoice = editInvoice;
        }
        
        setAllStates();
        setAllItems();
        
        // We set this in selectedCustomer object initially so that we can set the default here first then it can be modified
        invoice.setBillingEqualsShipping(true);
        
        invoice.setInvoiceNo((null==invoice.getInvoiceNo()) ? InvoiceManager.getNextInvoiceNo() : invoice.getInvoiceNo());
        invoice.setInvoiceType((null==invoice.getInvoiceType()) ? DEFAULT_INVOICE_TYPE : invoice.getInvoiceType());
        // change username to name
        //invoice.setSalesPerson((null==invoice.getSalesPerson()) ? SmartBooksUserSettings.USERNAME : invoice.getSalesPerson());
        invoice.setBillToAddress((null==invoice.getBillToAddress()) ? DEFAULT_BILLTO_ADDRESS : invoice.getBillToAddress());
        invoice.setBillToState((null==invoice.getBillToState()) ? DEFAULT_BILLTO_STATE : invoice.getBillToState());
        invoice.setBillToCity((null==invoice.getBillToCity()) ? DEFAULT_BILLTO_CITY : invoice.getBillToCity());
        invoice.setCustomerTax((null==invoice.getCustomerTax()) ? DEFAULT_CUSTOMER_TAX : invoice.getCustomerTax());
        invoice.setInvoiceDiscountType((null==invoice.getInvoiceDiscountType()) ? DEFAULT_INVOICE_DISCOUNT_TYPE : invoice.getInvoiceDiscountType());
        invoice.setInvoicePaymentType((null==invoice.getInvoicePaymentType()) ? DEFAULT_INVOICE_PAYMENT_TYPE : invoice.getInvoicePaymentType());
        
        initComponents();
        
        customInitComponents();
    }
    
    private void setAllStates() {
        this.states.addAll(stateCityMapping.keySet());
    }
    
    private void setAllItems() {
        this.items.clear();
        this.items = ItemManager.getAllActiveItems();
    }
    
    private void customInitComponents() {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        
        addKeyListenersToComponents(keyListener);
        
        if(invoice.getInvoiceId()==0) {
            invoicePanel.setBorder(new TitledBorder(invoicePanel.getBorder(), INVOICE_PANEL_CREATE_TEXT, 2, 0, new Font("Default", 0, 14)));
            createOrSaveInvoiceButton.setText(CREATE_BUTTON_TEXT);
        } else {
            invoicePanel.setBorder(new TitledBorder(invoicePanel.getBorder(), INVOICE_PANEL_EDIT_TEXT, 2, 0, new Font("Default", 0, 14)));
            createOrSaveInvoiceButton.setText(SAVE_BUTTON_TEXT);
        }
        
        grossAmountLabel.setText(df.format(invoice.getInvoiceGrossAmount()));
        taxAmountLabel.setText(df.format(invoice.getInvoiceTax()));
        discountAmountLabel.setText(df.format(invoice.getInvoiceDiscountValue()));
        netAmountLabel.setText(df.format(invoice.getInvoiceNetAmount()));
        
        populateCustomers();
        customerComboBox.setSelectedIndex(-1);
        
        populateSalesPerson();
        
        ((JTextField)customerComboBox.getEditor().getEditorComponent()).setDocument(new JTextFieldMaxLimitDocument(64));
        
        initializeInvoiceLinesTable();
    }
    
    private void addKeyListenersToComponents(KeyListener keyListener) {
        invoiceNoTextField.addKeyListener(keyListener);
        invoiceTypeComboBox.addKeyListener(keyListener);
        invoiceDateChooser.getComponent(1).addKeyListener(keyListener);
        salesPersonComboBox.addKeyListener(keyListener);
        poNoTextField.addKeyListener(keyListener);
        
        ((JTextField)customerComboBox.getEditor().getEditorComponent()).addKeyListener(keyListener);
        billToStateComboBox.addKeyListener(keyListener);
        billToCityComboBox.addKeyListener(keyListener);
        shipToStateComboBox.addKeyListener(keyListener);
        shipToCityComboBox.addKeyListener(keyListener);
        billingEqualsShippingCheckBox.addKeyListener(keyListener);
        customerTaxComboBox.addKeyListener(keyListener);
        
        discountTypeComboBox.addKeyListener(keyListener);
        discountValueTextField.addKeyListener(keyListener);
        paymentTypeComboBox.addKeyListener(keyListener);
        paymentAmountFormattedTextField.addKeyListener(keyListener);
    }
    
    /**
     * This method is used to get States
     * @return states
     */
    public ArrayList getStates() {
        return this.states;
    }
    
    /**
     * This method is used to set States
     * @param states
     */
    public void setStates(ArrayList states) {
        this.states = states;
    }
    
    /**
     * This method is used to get Invoice
     * @return invoice
     */
    public Invoice getInvoice() {
        return this.invoice;
    }
    
    /**
     * This method is used to set Invoice
     * @param invoice
     */
    public void setInvoice(Invoice invoice) {
        this.invoice = invoice;
    }
    
    private void populateCustomers() {
        customersMap.clear();
        
        ArrayList<Customer> customers = new ArrayList();
        customers = CustomerManager.getAllActiveCustomers();
        
        for(Customer customer : customers) {
            customersMap.put(customer.getCustomerName(), customer);
        }
        
        customerComboBox.setModel(new DefaultComboBoxModel(customersMap.keySet().toArray()));
    }
    
    private void populateCustomerDetailComponents(Customer customer) {
        billToAddressTextArea.setText(customer.getBillToAddress());
        billToStateComboBox.setSelectedItem(customer.getBillToState());
        billToCityComboBox.setSelectedItem(customer.getBillToCity());
        billingEqualsShippingCheckBox.setSelected(customer.isBillingEqualsShipping());
        shipToAddressTextArea.setText(customer.getShipToAddress());
        shipToStateComboBox.setSelectedItem(customer.getShipToState());
        shipToCityComboBox.setSelectedItem(customer.getShipToCity());
        customerTaxComboBox.setSelectedItem(customer.getCustomerTax());
    }
    
    private void populateSalesPerson() {
        ArrayList<String> salesPersons = UserOrganizationMappingManager.getActiveFirstnamesMappedToOrganization(SmartBooksUserSettings.DEFAULT_ORG_ID);

        salesPersonComboBox.setModel(new DefaultComboBoxModel(salesPersons.toArray()));

        String currentUserName = UserManager.getFirstnameByUsername(SmartBooksUserSettings.USERNAME);
        salesPersonComboBox.setSelectedItem(currentUserName);

        if(SmartBooksUserSettings.USER_ROLE.equals(USER_ROLE_EMPLOYEE)) {
            salesPersonComboBox.setEnabled(false);
        }
    }
    
    private void initializeInvoiceLinesTable() {
        invoiceLinesTable.setModel(new DefaultTableModel(columnNames, 8) {
            @Override
            public boolean isCellEditable(int row, int column) {
                return (column!=0 && column!=7);
            }
        });
        
        initColumnSizes();
        setUpComboBoxColumns();
        
        Action action = new AbstractAction()
        {
            @Override
            public void actionPerformed(ActionEvent e)
            {
                DecimalFormat df = new DecimalFormat("0.00");
                df.setMaximumFractionDigits(2);
                
                TableCellListener tcl = (TableCellListener)e.getSource();
                
                if(tcl.getColumn()==1 || tcl.getColumn()==5) {
                    try {
                        invoiceLinesTable.setValueAt(df.format(Double.parseDouble(tcl.getNewValue().toString())), tcl.getRow(), tcl.getColumn());
                        
                        double qty = Double.parseDouble(invoiceLinesTable.getValueAt(tcl.getRow(), 1).toString());
                        double sellingPrice = Double.parseDouble(invoiceLinesTable.getValueAt(tcl.getRow(), 5).toString());
                        // Also consider tax over here properly
                        String total = df.format(qty*sellingPrice);
                        invoiceLinesTable.setValueAt(total, tcl.getRow(), 7);
                    } catch(NullPointerException | NumberFormatException ex) {
                        invoiceLinesTable.setValueAt("", tcl.getRow(), 7);
                    }
                    
                    calculateGrossAmount();
                    calculateDiscountAmount();
                    calculateNetAmount();
                    
                    updateNoColumnOfTable();
                }
            }
        };
        
        TableCellListener tcl = new TableCellListener(invoiceLinesTable, action);
    }
    
    private void setUpComboBoxColumns() {
        //Set up the editor for the Quantity cells.
        //NumberFormat format = NumberFormat.getInstance();
        //NumberFormatter formatter = new NumberFormatter(format);
        //formatter.setValueClass(Double.class);
        //formatter.setAllowsInvalid(false);
        // If you want the value to be committed on each keystroke instead of focus lost
        //formatter.setCommitsOnValidEdit(true);
        JTextField qtyTextField = new JTextField();
        qtyTextField.addKeyListener(new TextFieldItemKeyListener());
        invoiceLinesTable.getColumnModel().getColumn(1).setCellEditor(new DefaultCellEditor(qtyTextField));
        
        //Set up the editor for the Item Name cells.
        JComboBox itemNameComboBox = new JComboBox();
        for(Item item : items) {
            if(null!=item.getItemName() && !item.getItemName().equals("")) {
                itemNameComboBox.addItem(new MyComboBoxItem(item.getItemName()));
            }
        }
        itemNameComboBox.setEditable(true);
        ((JTextField)itemNameComboBox.getEditor().getEditorComponent()).setDocument(new JTextFieldMaxLimitDocument(64));
        itemNameComboBox.addActionListener(new ComboBoxItemActionListener());        
        invoiceLinesTable.getColumnModel().getColumn(2).setCellEditor(new DefaultCellEditor(itemNameComboBox));
        
        //Set up the editor for the Item Code cells.
        JComboBox itemCodeComboBox = new JComboBox();
        for(Item item : items) {
            if(null!=item.getItemCode() && !item.getItemCode().equals("")) {
                itemCodeComboBox.addItem(new MyComboBoxItem(item.getItemCode()));
            }
        }
        itemCodeComboBox.setEditable(true);
        ((JTextField)itemCodeComboBox.getEditor().getEditorComponent()).setDocument(new JTextFieldMaxLimitDocument(64));
        itemCodeComboBox.addActionListener(new ComboBoxItemActionListener());
        invoiceLinesTable.getColumnModel().getColumn(3).setCellEditor(new DefaultCellEditor(itemCodeComboBox));
        
        //Set up the editor for the Item Description cells.
        JComboBox itemDescriptionComboBox = new JComboBox();
        for(Item item : items) {
            if(null!=item.getItemDescription() && !item.getItemDescription().equals("")) {
                itemDescriptionComboBox.addItem(new MyComboBoxItem(item.getItemDescription()));
            }
        }
        itemDescriptionComboBox.setEditable(true);
        ((JTextField)itemDescriptionComboBox.getEditor().getEditorComponent()).setDocument(new JTextFieldMaxLimitDocument(256));
        itemDescriptionComboBox.addActionListener(new ComboBoxItemActionListener());
        invoiceLinesTable.getColumnModel().getColumn(4).setCellEditor(new DefaultCellEditor(itemDescriptionComboBox));
        
        //Set up the editor for the Item Tax cells.
        JComboBox itemTaxComboBox = new JComboBox();
        itemTaxComboBox.addItem(new MyComboBoxItem("Exempt"));
        invoiceLinesTable.getColumnModel().getColumn(6).setCellEditor(new DefaultCellEditor(itemTaxComboBox));
        
        //Set up the editor for the Selling Price cells.
        JTextField sellingPriceTextField = new JTextField();
        sellingPriceTextField.addKeyListener(new TextFieldItemKeyListener());
        invoiceLinesTable.getColumnModel().getColumn(5).setCellEditor(new DefaultCellEditor(sellingPriceTextField));
    }
    
    private static class MyComboBoxItem {
        private String value;

        public MyComboBoxItem(String value) {
            this.value = value;
        }

        public String getValue() {
            return value;
        }

        @Override
        public String toString() {
            return value; //this is what display in the JComboBox
        }
    }
    
    class TextFieldItemKeyListener implements KeyListener {
        @Override
        public void keyTyped(KeyEvent e) {
            CommonFunctions.addFloatPatternKeyTypedListener(e);
        }

        @Override
        public void keyPressed(KeyEvent e) { }

        @Override
        public void keyReleased(KeyEvent e) { }
    }
    
    class ComboBoxItemActionListener implements ActionListener {
        @Override
        public void actionPerformed(ActionEvent e){
            DecimalFormat df = new DecimalFormat("0.00");
            df.setMaximumFractionDigits(2);
            
            int selectedRow = invoiceLinesTable.getSelectedRow();
            int selectedColumn = invoiceLinesTable.getSelectedColumn();
            
            if(selectedRow>=0) {
                JComboBox comboBox = (JComboBox) e.getSource();
                int selectedIndex = comboBox.getSelectedIndex();
                if(selectedIndex>=0) {
                    Item item = items.get(selectedIndex);
                    
                    if(selectedColumn==2) { // for Item Name
                        invoiceLinesTable.setValueAt(item.getItemCode(), selectedRow, 3);
                        invoiceLinesTable.setValueAt(item.getItemDescription(), selectedRow, 4);
                        invoiceLinesTable.setValueAt(df.format(item.getSellingPrice()), selectedRow, 5);
                        // Set the tax properly
                        //invoiceLinesTable.setValueAt(item.getItemTaxId(), selectedRow, 6);
                    } else if(selectedColumn==3) { // for Item Code
                        invoiceLinesTable.setValueAt(item.getItemName(), selectedRow, 2);
                        invoiceLinesTable.setValueAt(item.getItemDescription(), selectedRow, 4);
                        invoiceLinesTable.setValueAt(df.format(item.getSellingPrice()), selectedRow, 5);
                        // Set the tax properly
                        //invoiceLinesTable.setValueAt(item.getItemTaxId(), selectedRow, 6);
                    } else if(selectedColumn==4) { // for Item Description
                        invoiceLinesTable.setValueAt(item.getItemName(), selectedRow, 2);
                        invoiceLinesTable.setValueAt(item.getItemCode(), selectedRow, 3);
                        invoiceLinesTable.setValueAt(df.format(item.getSellingPrice()), selectedRow, 5);
                        // Set the tax properly
                        //invoiceLinesTable.setValueAt(item.getItemTaxId(), selectedRow, 6);
                    }
                    
                    try {
                        double qty = Double.parseDouble(invoiceLinesTable.getValueAt(selectedRow, 1).toString());
                        double sellingPrice = Double.parseDouble(invoiceLinesTable.getValueAt(selectedRow, 5).toString());
                        
                        // Also consider tax over here properly
                        String total = df.format(qty*sellingPrice);
                        invoiceLinesTable.setValueAt(total, selectedRow, 7);
                    } catch(NullPointerException | NumberFormatException npe) {
                        invoiceLinesTable.setValueAt("", selectedRow, 7);
                    }
                    
                    calculateGrossAmount();
                    calculateNetAmount();
                    
                    updateNoColumnOfTable();
                }
            }
        }
    }
    
    class ItemFocusListener implements FocusListener {
        @Override
        public void focusGained(FocusEvent e) { }

        @Override
        public void focusLost(FocusEvent e) {
            
        }
    }
    
    private void initColumnSizes() {
        double[] columnSizes = {0.01,0.10,0.18,0.12,0.35,0.10,0.10,0.10};
        Dimension tableSize =  invoiceLinesTable.getPreferredSize();
        
        for(int i=0; i<invoiceLinesTable.getColumnCount(); i++) {
            invoiceLinesTable.getColumnModel().getColumn(i).setPreferredWidth((int) Math.round(tableSize.width*columnSizes[i]));
        }
    }
    
    private void updateNoColumnOfTable() {
        int minUpdateRow = 0;
        int maxUpdateRow = -1;
        
        int rows = invoiceLinesTable.getRowCount();
        int cols = invoiceLinesTable.getColumnCount();
        for(int i=0; i<rows; i++) {
            for(int j=0; j<cols; j++) {
                if(null!=invoiceLinesTable.getValueAt(i,j) && !invoiceLinesTable.getValueAt(i,j).equals("")) {
                    maxUpdateRow = i;
                    break;
                }
            }
        }
        
        for(int m=minUpdateRow; m<=maxUpdateRow; m++) {
            invoiceLinesTable.setValueAt(m+1, m, 0);
        }
    }
    
    private void calculateGrossAmount() {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        double grossAmount = 0;
        
        int rows = invoiceLinesTable.getRowCount();
        for(int i=0; i<rows; i++) {
            if(null!=invoiceLinesTable.getValueAt(i,7) && !invoiceLinesTable.getValueAt(i,7).equals("")) {
                grossAmount += Double.parseDouble(invoiceLinesTable.getValueAt(i,7).toString());
            }
        }
        
        grossAmountLabel.setText(df.format(grossAmount));
    }
    
    private void calculateDiscountAmount() {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        double discountValue = 0;
        
        if(null!=discountValueTextField.getText() && !discountValueTextField.getText().equals("")) {
            discountValue = Double.parseDouble(discountValueTextField.getText());
        }
        
        if(discountTypeComboBox.getSelectedItem().equals("%")) {
            double grossAmount = 0;
            double taxAmount = 0;
            if(null!=grossAmountLabel.getText() && !grossAmountLabel.getText().equals("")) {
                grossAmount = Double.parseDouble(grossAmountLabel.getText());
            }
            if(null!=taxAmountLabel.getText() && !taxAmountLabel.getText().equals("")) {
                taxAmount = Double.parseDouble(taxAmountLabel.getText());
            }
            
            discountAmountLabel.setText(df.format((grossAmount+taxAmount)*discountValue/100));
        } else {
            discountAmountLabel.setText(df.format(discountValue));
        }
        
        calculateNetAmount();
    }
    
    private void calculateNetAmount() {
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        double grossAmount = 0;
        double taxAmount = 0;
        double discountAmount = 0;
        double netAmount = 0;
        
        if(null!=grossAmountLabel.getText() && !grossAmountLabel.getText().equals("")) {
            grossAmount = Double.parseDouble(grossAmountLabel.getText());
        }
        
        if(null!=taxAmountLabel.getText() && !taxAmountLabel.getText().equals("")) {
            taxAmount = Double.parseDouble(taxAmountLabel.getText());
        }
        
        if(null!=discountAmountLabel.getText() && !discountAmountLabel.getText().equals("")) {
            discountAmount = Double.parseDouble(discountAmountLabel.getText());
        }
        
        if(grossAmount==0) {
            netAmount = 0;
        } else {
            netAmount = grossAmount + taxAmount - discountAmount;
        }
        
        netAmountLabel.setText(df.format(netAmount));
    }
    
    private void setShipToAddressAsBillToAddress() {
        shipToAddressTextArea.setText(billToAddressTextArea.getText().equals(DEFAULT_BILLTO_ADDRESS) ? "" : billToAddressTextArea.getText());
        shipToStateComboBox.setSelectedItem(billToStateComboBox.getSelectedItem());
        shipToCityComboBox.setSelectedItem(billToCityComboBox.getSelectedItem());
        
        shipToAddressTextArea.setForeground(Color.GRAY);
    }
    
    private void assignAdditionalInvoiceValues(String invoiceModificationType) {
        if(null!=invoice.getBillToAddress() && invoice.getBillToAddress().equals(DEFAULT_BILLTO_ADDRESS)) {
            invoice.setBillToAddress(null);
        }
        if(null!=invoice.getBillToState() && invoice.getBillToState().equals(DEFAULT_BILLTO_STATE)) {
            invoice.setBillToState(null);
        }
        if(null!=invoice.getBillToCity() && invoice.getBillToCity().equals(DEFAULT_BILLTO_CITY)) {
            invoice.setBillToCity(null);
        }
        
        if(null!=invoice.getShipToAddress() && invoice.getShipToAddress().equals(DEFAULT_SHIPTO_ADDRESS)) {
            invoice.setShipToAddress(null);
        }
        if(null!=invoice.getShipToState() && invoice.getShipToState().equals(DEFAULT_SHIPTO_STATE)) {
            invoice.setShipToState(null);
        }
        if(null!=invoice.getShipToCity() && invoice.getShipToCity().equals(DEFAULT_SHIPTO_CITY)) {
            invoice.setShipToCity(null);
        }
        
        invoice.setInvoiceDate(invoiceDateChooser.getDate());
        
        String customerName = String.valueOf(customerComboBox.getSelectedItem());
        Customer customer = customersMap.get(customerName);
        if(null!=customer) {
            invoice.setCustomerId(customer.getCustomerId());
        }
        
        if(null!=discountValueTextField.getText() && discountValueTextField.getText().length()>0) {
            invoice.setInvoiceDiscountValue(Double.valueOf(discountValueTextField.getText()));
        }
        
        if(null!=paymentAmountFormattedTextField.getText() && paymentAmountFormattedTextField.getText().length()>0) {
            invoice.setInvoicePaymentAmount(Double.valueOf(paymentAmountFormattedTextField.getText()));
        }
        
        if(invoiceModificationType.equals(CREATE_BUTTON_TEXT)) {
            invoice.setCreatedBy(SmartBooksUserSettings.USERNAME);
        }
        invoice.setUpdatedBy(SmartBooksUserSettings.USERNAME);
    }
    
    private void assignAdditionalInvoiceLinesValues(String invoiceModificationType) {
        invoiceLinesList.clear();
        
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        
        int rows = invoiceLinesTable.getRowCount();
        for(int i=0; i<rows; i++) {
            if(null==invoiceLinesTable.getValueAt(i,0) || invoiceLinesTable.getValueAt(i,0).equals("")) {
                break;
            }
            
            InvoiceLines invoiceLines = new InvoiceLines();
            
            double qty = (null!=invoiceLinesTable.getValueAt(i,1) && !invoiceLinesTable.getValueAt(i,1).equals("")) ? Double.parseDouble((String)invoiceLinesTable.getValueAt(i,1)) : 0;
            invoiceLines.setQuantity(qty);
            
            String itemName = (null!=invoiceLinesTable.getValueAt(i,2)) ? (String)invoiceLinesTable.getValueAt(i,2).toString() : "";
            invoiceLines.setItemName(itemName);
            
            String itemCode = (null!=invoiceLinesTable.getValueAt(i,3)) ? (String)invoiceLinesTable.getValueAt(i,3).toString() : "";
            invoiceLines.setItemCode(itemCode);
            
            String itemDescription = (null!=invoiceLinesTable.getValueAt(i,4)) ? (String)invoiceLinesTable.getValueAt(i,4).toString() : "";
            invoiceLines.setItemDescription(itemDescription);
            
            double sellingPrice = (null!=invoiceLinesTable.getValueAt(i,5) && !invoiceLinesTable.getValueAt(i,5).equals("")) ? Double.parseDouble((String)invoiceLinesTable.getValueAt(i,5)) : 0;
            invoiceLines.setSellingPrice(sellingPrice);
            
            String taxName = (null!=invoiceLinesTable.getValueAt(i,6)) ? (String)invoiceLinesTable.getValueAt(i,6).toString() : "";
            invoiceLines.setTaxName(taxName);
            
            double itemTotal = (null!=invoiceLinesTable.getValueAt(i,7) && !invoiceLinesTable.getValueAt(i,7).equals("")) ? Double.parseDouble((String)invoiceLinesTable.getValueAt(i,7)) : 0;
            invoiceLines.setItemTotal(itemTotal);
            
            if(invoiceModificationType.equals(CREATE_BUTTON_TEXT)) {
                invoiceLines.setCreatedBy(SmartBooksUserSettings.USERNAME);
            }
            invoiceLines.setUpdatedBy(SmartBooksUserSettings.USERNAME);
            
            invoiceLinesList.add(invoiceLines);
        }
    }
    
    private void setModifiedInvoiceInParent() {
        Container c = this;
        
        while(c.getParent()!=null) {
            c = c.getParent();
            
            if(c instanceof InvoicesDialog) {
                ((InvoicesDialog)c).setModifiedInvoice(invoice);
            }
        }
    }
    
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {
        bindingGroup = new org.jdesktop.beansbinding.BindingGroup();

        invoicePanel = new javax.swing.JPanel();
        addressTabbedPane = new javax.swing.JTabbedPane();
        jPanel2 = new javax.swing.JPanel();
        jLabel1 = new javax.swing.JLabel();
        customerComboBox = new javax.swing.JComboBox();
        addEditCustomerButton = new javax.swing.JButton();
        jLabel2 = new javax.swing.JLabel();
        jScrollPane1 = new javax.swing.JScrollPane();
        billToAddressTextArea = new javax.swing.JTextArea();
        billToStateComboBox = new javax.swing.JComboBox();
        jLabel23 = new javax.swing.JLabel();
        billToCityComboBox = new javax.swing.JComboBox();
        jLabel24 = new javax.swing.JLabel();
        jLabel8 = new javax.swing.JLabel();
        customerTaxComboBox = new javax.swing.JComboBox();
        jPanel3 = new javax.swing.JPanel();
        jLabel16 = new javax.swing.JLabel();
        jScrollPane5 = new javax.swing.JScrollPane();
        shipToAddressTextArea = new javax.swing.JTextArea();
        shipToStateComboBox = new javax.swing.JComboBox();
        jLabel25 = new javax.swing.JLabel();
        shipToCityComboBox = new javax.swing.JComboBox();
        jLabel26 = new javax.swing.JLabel();
        billingEqualsShippingCheckBox = new javax.swing.JCheckBox();
        detailsTabbedPane = new javax.swing.JTabbedPane();
        jPanel4 = new javax.swing.JPanel();
        jLabel3 = new javax.swing.JLabel();
        jLabel4 = new javax.swing.JLabel();
        invoiceTypeComboBox = new javax.swing.JComboBox();
        jLabel5 = new javax.swing.JLabel();
        invoiceDateChooser = new com.toedter.calendar.JDateChooser("dd/MM/yyyy","##/##/####",' ');
        jLabel6 = new javax.swing.JLabel();
        salesPersonComboBox = new javax.swing.JComboBox();
        jLabel7 = new javax.swing.JLabel();
        poNoTextField = new javax.swing.JTextField();
        invoiceNoTextField = new javax.swing.JTextField();
        jScrollPane2 = new javax.swing.JScrollPane();
        invoiceLinesTable = new javax.swing.JTable();
        addItemButton = new javax.swing.JButton();
        removeItemButton = new javax.swing.JButton();
        moveUpItemButton = new javax.swing.JButton();
        moveDownItemButton = new javax.swing.JButton();
        publicNotesPanel = new javax.swing.JPanel();
        jScrollPane3 = new javax.swing.JScrollPane();
        publicNotesTextArea = new javax.swing.JTextArea();
        privateNotesPanel = new javax.swing.JPanel();
        jScrollPane4 = new javax.swing.JScrollPane();
        privateNotesTextArea = new javax.swing.JTextArea();
        amountPanel = new javax.swing.JPanel();
        jLabel9 = new javax.swing.JLabel();
        grossAmountLabel = new javax.swing.JLabel();
        jLabel10 = new javax.swing.JLabel();
        taxAmountLabel = new javax.swing.JLabel();
        jLabel11 = new javax.swing.JLabel();
        discountTypeComboBox = new javax.swing.JComboBox();
        discountValueTextField = new javax.swing.JTextField();
        discountAmountLabel = new javax.swing.JLabel();
        jSeparator1 = new javax.swing.JSeparator();
        jLabel14 = new javax.swing.JLabel();
        netAmountLabel = new javax.swing.JLabel();
        jLabel22 = new javax.swing.JLabel();
        paymentTypeComboBox = new javax.swing.JComboBox();
        paymentAmountFormattedTextField = new javax.swing.JFormattedTextField();
        jSeparator2 = new javax.swing.JSeparator();
        invoiceOptionsButton = new javax.swing.JButton();
        previewInvoiceButton = new javax.swing.JButton();
        clearInvoiceButton = new javax.swing.JButton();
        createOrSaveInvoiceButton = new javax.swing.JButton();

        invoicePanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, " ", javax.swing.border.TitledBorder.CENTER, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 14))); // NOI18N

        addressTabbedPane.setFocusable(false);
        addressTabbedPane.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        jPanel2.setFocusable(false);
        jPanel2.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        jLabel1.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel1.setText("Customer:");

        customerComboBox.setEditable(true);
        customerComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        customerComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                customerComboBoxItemStateChanged(evt);
            }
        });

        addEditCustomerButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        addEditCustomerButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/smartbooks/images/add_edit_customer_16-16.png"))); // NOI18N
        addEditCustomerButton.setToolTipText("Add/Edit Customer");
        addEditCustomerButton.setFocusable(false);
        addEditCustomerButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addEditCustomerButtonActionPerformed(evt);
            }
        });

        jLabel2.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel2.setText("Bill To:");

        jScrollPane1.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        billToAddressTextArea.setColumns(20);
        billToAddressTextArea.setDocument(new JTextFieldMaxLimitDocument(256));
        billToAddressTextArea.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
        billToAddressTextArea.setForeground(new java.awt.Color(128, 128, 128));
        billToAddressTextArea.setLineWrap(true);
        billToAddressTextArea.setRows(3);
        billToAddressTextArea.setWrapStyleWord(true);

        org.jdesktop.beansbinding.Binding binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.billToAddress}"), billToAddressTextArea, org.jdesktop.beansbinding.BeanProperty.create("text"), "billToAddressBinding");
        bindingGroup.addBinding(binding);

        billToAddressTextArea.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                billToAddressTextAreaFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                billToAddressTextAreaFocusLost(evt);
            }
        });
        billToAddressTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                billToAddressTextAreaKeyPressed(evt);
            }
            public void keyReleased(java.awt.event.KeyEvent evt) {
                billToAddressTextAreaKeyReleased(evt);
            }
        });
        jScrollPane1.setViewportView(billToAddressTextArea);

        billToStateComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        org.jdesktop.beansbinding.ELProperty eLProperty = org.jdesktop.beansbinding.ELProperty.create("${states}");
        org.jdesktop.swingbinding.JComboBoxBinding jComboBoxBinding = org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, eLProperty, billToStateComboBox, "billToAllStatesBinding");
        bindingGroup.addBinding(jComboBoxBinding);
        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.billToState}"), billToStateComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "billToStateBinding");
        bindingGroup.addBinding(binding);

        billToStateComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                billToStateComboBoxItemStateChanged(evt);
            }
        });

        jLabel23.setText("State");
        jLabel23.setEnabled(false);

        billToCityComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.billToCity}"), billToCityComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "billToCityBinding");
        bindingGroup.addBinding(binding);

        billToCityComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                billToCityComboBoxItemStateChanged(evt);
            }
        });

        jLabel24.setText("City");
        jLabel24.setEnabled(false);

        jLabel8.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel8.setText("Customer Tax:");

        customerTaxComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        customerTaxComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Default", "Exempt" }));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.customerTax}"), customerTaxComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "customerTaxBinding");
        bindingGroup.addBinding(binding);

        javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(jPanel2);
        jPanel2.setLayout(jPanel2Layout);
        jPanel2Layout.setHorizontalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel1, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel2, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel8, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jScrollPane1)
                    .addGroup(jPanel2Layout.createSequentialGroup()
                        .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addComponent(customerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 279, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(addEditCustomerButton, javax.swing.GroupLayout.PREFERRED_SIZE, 39, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(jPanel2Layout.createSequentialGroup()
                                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(billToStateComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE)
                                    .addComponent(jLabel23))
                                .addGap(18, 18, 18)
                                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                                    .addComponent(jLabel24)
                                    .addComponent(billToCityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE)))
                            .addComponent(customerTaxComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 328, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(0, 0, Short.MAX_VALUE)))
                .addContainerGap())
        );
        jPanel2Layout.setVerticalGroup(
            jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel2Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel1)
                    .addComponent(customerComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(addEditCustomerButton))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel2)
                    .addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(billToStateComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(billToCityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel23)
                    .addComponent(jLabel24))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel2Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel8)
                    .addComponent(customerTaxComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(13, Short.MAX_VALUE))
        );

        addressTabbedPane.addTab("Billing", jPanel2);

        jLabel16.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel16.setText("Ship To:");

        jScrollPane5.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        shipToAddressTextArea.setColumns(20);
        shipToAddressTextArea.setDocument(new JTextFieldMaxLimitDocument(256));
        shipToAddressTextArea.setFont(new java.awt.Font("Monospaced", 0, 12)); // NOI18N
        shipToAddressTextArea.setForeground(new java.awt.Color(128, 128, 128));
        shipToAddressTextArea.setLineWrap(true);
        shipToAddressTextArea.setRows(3);
        shipToAddressTextArea.setWrapStyleWord(true);
        shipToAddressTextArea.setEnabled(false);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.shipToAddress}"), shipToAddressTextArea, org.jdesktop.beansbinding.BeanProperty.create("text"), "shipToAddressBinding");
        bindingGroup.addBinding(binding);

        shipToAddressTextArea.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusGained(java.awt.event.FocusEvent evt) {
                shipToAddressTextAreaFocusGained(evt);
            }
            public void focusLost(java.awt.event.FocusEvent evt) {
                shipToAddressTextAreaFocusLost(evt);
            }
        });
        shipToAddressTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                shipToAddressTextAreaKeyPressed(evt);
            }
        });
        jScrollPane5.setViewportView(shipToAddressTextArea);

        shipToStateComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        shipToStateComboBox.setEnabled(false);

        eLProperty = org.jdesktop.beansbinding.ELProperty.create("${states}");
        jComboBoxBinding = org.jdesktop.swingbinding.SwingBindings.createJComboBoxBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, eLProperty, shipToStateComboBox, "shipToAllStatesBinding");
        bindingGroup.addBinding(jComboBoxBinding);
        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.shipToState}"), shipToStateComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "shipToStateBinding");
        bindingGroup.addBinding(binding);

        shipToStateComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                shipToStateComboBoxItemStateChanged(evt);
            }
        });

        jLabel25.setText("State");
        jLabel25.setEnabled(false);

        shipToCityComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        shipToCityComboBox.setEnabled(false);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.shipToCity}"), shipToCityComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "shipToCityBinding");
        bindingGroup.addBinding(binding);

        jLabel26.setText("City");
        jLabel26.setEnabled(false);

        billingEqualsShippingCheckBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        billingEqualsShippingCheckBox.setText("Same as 'Bill To' Address");

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.billingEqualsShipping}"), billingEqualsShippingCheckBox, org.jdesktop.beansbinding.BeanProperty.create("selected"), "billingEqualsShippingBinding");
        bindingGroup.addBinding(binding);

        billingEqualsShippingCheckBox.addChangeListener(new javax.swing.event.ChangeListener() {
            public void stateChanged(javax.swing.event.ChangeEvent evt) {
                billingEqualsShippingCheckBoxStateChanged(evt);
            }
        });

        javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3);
        jPanel3.setLayout(jPanel3Layout);
        jPanel3Layout.setHorizontalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(jPanel3Layout.createSequentialGroup()
                        .addGap(44, 44, 44)
                        .addComponent(jLabel16)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(jScrollPane5, javax.swing.GroupLayout.DEFAULT_SIZE, 328, Short.MAX_VALUE))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup()
                        .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(shipToStateComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 186, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(jLabel25)
                            .addComponent(billingEqualsShippingCheckBox))
                        .addGap(18, 18, 18)
                        .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(jLabel26)
                            .addComponent(shipToCityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, 124, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addContainerGap())
        );
        jPanel3Layout.setVerticalGroup(
            jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel3Layout.createSequentialGroup()
                .addGap(49, 49, 49)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel16)
                    .addComponent(jScrollPane5, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(shipToStateComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(shipToCityComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                .addGroup(jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel25)
                    .addComponent(jLabel26))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(billingEqualsShippingCheckBox)
                .addContainerGap(13, Short.MAX_VALUE))
        );

        addressTabbedPane.addTab("Shipping", jPanel3);

        detailsTabbedPane.setFocusable(false);
        detailsTabbedPane.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        jLabel3.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel3.setText("<html><font color=red>*</font>Invoice No:</html>");

        jLabel4.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel4.setText("Type:");

        invoiceTypeComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        invoiceTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "New Invoice", "Draft", "Return" }));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceType}"), invoiceTypeComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "invoiceTypeBinding");
        bindingGroup.addBinding(binding);

        jLabel5.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel5.setText("Date:");

        invoiceDateChooser.setDate(new Date());
        invoiceDateChooser.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        jLabel6.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel6.setText("Salesperson:");

        salesPersonComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        salesPersonComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Item 1", "Item 2", "Item 3", "Item 4" }));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.salesPerson}"), salesPersonComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "salesPersonBinding");
        bindingGroup.addBinding(binding);

        jLabel7.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel7.setText("PO No:");

        poNoTextField.setDocument(new JTextFieldMaxLimitDocument(32));
        poNoTextField.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoicePONo}"), poNoTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoicePONoBinding");
        bindingGroup.addBinding(binding);

        invoiceNoTextField.setDocument(new JTextFieldMaxLimitDocument(16));
        invoiceNoTextField.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceNo}"), invoiceNoTextField, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoiceNoBinding");
        bindingGroup.addBinding(binding);

        invoiceNoTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                invoiceNoTextFieldKeyTyped(evt);
            }
        });

        javax.swing.GroupLayout jPanel4Layout = new javax.swing.GroupLayout(jPanel4);
        jPanel4.setLayout(jPanel4Layout);
        jPanel4Layout.setHorizontalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jLabel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(jLabel4, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel5, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel6, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addComponent(jLabel7, javax.swing.GroupLayout.Alignment.TRAILING))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                    .addComponent(invoiceTypeComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, 230, Short.MAX_VALUE)
                    .addComponent(invoiceDateChooser, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(poNoTextField, javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(salesPersonComboBox, javax.swing.GroupLayout.Alignment.LEADING, 0, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(invoiceNoTextField, javax.swing.GroupLayout.Alignment.LEADING))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );
        jPanel4Layout.setVerticalGroup(
            jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(jPanel4Layout.createSequentialGroup()
                .addContainerGap()
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(invoiceNoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel4)
                    .addComponent(invoiceTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel5)
                    .addComponent(invoiceDateChooser, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel6)
                    .addComponent(salesPersonComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(jPanel4Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                    .addComponent(jLabel7)
                    .addComponent(poNoTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addContainerGap(37, Short.MAX_VALUE))
        );

        detailsTabbedPane.addTab("Details", jPanel4);

        invoiceLinesTable.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        invoiceLinesTable.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {
                {"", null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null},
                {null, null, null, null, null, null, null, null}
            },
            new String [] {
                "No", "Qty", "Item Name", "Item Code", "Description", "Selling Price", "Tax", "Total"
            }
        ));
        jScrollPane2.setViewportView(invoiceLinesTable);

        addItemButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        addItemButton.setText("Add Item");
        addItemButton.setFocusable(false);
        addItemButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                addItemButtonActionPerformed(evt);
            }
        });

        removeItemButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        removeItemButton.setText("Remove Item");
        removeItemButton.setFocusable(false);
        removeItemButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                removeItemButtonActionPerformed(evt);
            }
        });

        moveUpItemButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        moveUpItemButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/smartbooks/images/up_20-20.png"))); // NOI18N
        moveUpItemButton.setFocusable(false);
        moveUpItemButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveUpItemButtonActionPerformed(evt);
            }
        });

        moveDownItemButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        moveDownItemButton.setIcon(new javax.swing.ImageIcon(getClass().getResource("/smartbooks/images/down_20-20.png"))); // NOI18N
        moveDownItemButton.setFocusable(false);
        moveDownItemButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                moveDownItemButtonActionPerformed(evt);
            }
        });

        publicNotesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Public Notes", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N
        publicNotesPanel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        jScrollPane3.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        publicNotesTextArea.setColumns(20);
        publicNotesTextArea.setDocument(new JTextFieldMaxLimitDocument(256));
        publicNotesTextArea.setLineWrap(true);
        publicNotesTextArea.setRows(6);
        publicNotesTextArea.setWrapStyleWord(true);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoicePublicNotes}"), publicNotesTextArea, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoicePublicNotesBinding");
        bindingGroup.addBinding(binding);

        publicNotesTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                publicNotesTextAreaKeyPressed(evt);
            }
        });
        jScrollPane3.setViewportView(publicNotesTextArea);

        javax.swing.GroupLayout publicNotesPanelLayout = new javax.swing.GroupLayout(publicNotesPanel);
        publicNotesPanel.setLayout(publicNotesPanelLayout);
        publicNotesPanelLayout.setHorizontalGroup(
            publicNotesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
        publicNotesPanelLayout.setVerticalGroup(
            publicNotesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        privateNotesPanel.setBorder(javax.swing.BorderFactory.createTitledBorder(null, "Private Notes", javax.swing.border.TitledBorder.DEFAULT_JUSTIFICATION, javax.swing.border.TitledBorder.DEFAULT_POSITION, new java.awt.Font("Tahoma", 0, 12))); // NOI18N
        privateNotesPanel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N

        jScrollPane4.setVerticalScrollBarPolicy(javax.swing.ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS);

        privateNotesTextArea.setColumns(20);
        privateNotesTextArea.setDocument(new JTextFieldMaxLimitDocument(256));
        privateNotesTextArea.setLineWrap(true);
        privateNotesTextArea.setRows(6);
        privateNotesTextArea.setWrapStyleWord(true);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoicePrivateNotes}"), privateNotesTextArea, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoicePrivateNotesBinding");
        bindingGroup.addBinding(binding);

        privateNotesTextArea.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyPressed(java.awt.event.KeyEvent evt) {
                privateNotesTextAreaKeyPressed(evt);
            }
        });
        jScrollPane4.setViewportView(privateNotesTextArea);

        javax.swing.GroupLayout privateNotesPanelLayout = new javax.swing.GroupLayout(privateNotesPanel);
        privateNotesPanel.setLayout(privateNotesPanelLayout);
        privateNotesPanelLayout.setHorizontalGroup(
            privateNotesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );
        privateNotesPanelLayout.setVerticalGroup(
            privateNotesPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(jScrollPane4, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        amountPanel.setBorder(javax.swing.BorderFactory.createEtchedBorder());

        jLabel9.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel9.setText("Gross Amount:");

        grossAmountLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        grossAmountLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceGrossAmount}"), grossAmountLabel, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoiceGrossAmountBinding");
        bindingGroup.addBinding(binding);

        jLabel10.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel10.setText("Tax:");

        taxAmountLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        taxAmountLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceTax}"), taxAmountLabel, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoiceTaxBinding");
        bindingGroup.addBinding(binding);

        jLabel11.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel11.setText("Discount:");

        discountTypeComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        discountTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "%", "-" }));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceDiscountType}"), discountTypeComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "invoiceDiscountTypeBinding");
        bindingGroup.addBinding(binding);

        discountTypeComboBox.addItemListener(new java.awt.event.ItemListener() {
            public void itemStateChanged(java.awt.event.ItemEvent evt) {
                discountTypeComboBoxItemStateChanged(evt);
            }
        });

        discountValueTextField.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        discountValueTextField.addFocusListener(new java.awt.event.FocusAdapter() {
            public void focusLost(java.awt.event.FocusEvent evt) {
                discountValueTextFieldFocusLost(evt);
            }
        });
        discountValueTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                discountValueTextFieldKeyReleased(evt);
            }
            public void keyTyped(java.awt.event.KeyEvent evt) {
                discountValueTextFieldKeyTyped(evt);
            }
        });

        discountAmountLabel.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        discountAmountLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceDiscountValue}"), discountAmountLabel, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoiceDiscountValueBinding");
        bindingGroup.addBinding(binding);

        jLabel14.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        jLabel14.setForeground(new java.awt.Color(0, 153, 0));
        jLabel14.setText("Net Amount:");

        netAmountLabel.setFont(new java.awt.Font("Tahoma", 0, 14)); // NOI18N
        netAmountLabel.setForeground(new java.awt.Color(0, 153, 0));
        netAmountLabel.setHorizontalAlignment(javax.swing.SwingConstants.RIGHT);

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoiceNetAmount}"), netAmountLabel, org.jdesktop.beansbinding.BeanProperty.create("text"), "invoiceNetAmountBinding");
        bindingGroup.addBinding(binding);

        javax.swing.GroupLayout amountPanelLayout = new javax.swing.GroupLayout(amountPanel);
        amountPanel.setLayout(amountPanelLayout);
        amountPanelLayout.setHorizontalGroup(
            amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(amountPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSeparator1, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(amountPanelLayout.createSequentialGroup()
                        .addComponent(jLabel11)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addComponent(discountTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                        .addGroup(amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addComponent(taxAmountLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addGroup(amountPanelLayout.createSequentialGroup()
                                .addGap(1, 1, 1)
                                .addComponent(discountValueTextField, javax.swing.GroupLayout.PREFERRED_SIZE, 66, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(discountAmountLabel, javax.swing.GroupLayout.PREFERRED_SIZE, 95, javax.swing.GroupLayout.PREFERRED_SIZE))))
                    .addGroup(amountPanelLayout.createSequentialGroup()
                        .addComponent(jLabel14)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(netAmountLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                    .addGroup(amountPanelLayout.createSequentialGroup()
                        .addComponent(jLabel10)
                        .addGap(0, 0, Short.MAX_VALUE))
                    .addGroup(amountPanelLayout.createSequentialGroup()
                        .addComponent(jLabel9)
                        .addGap(18, 18, 18)
                        .addComponent(grossAmountLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)))
                .addContainerGap())
        );
        amountPanelLayout.setVerticalGroup(
            amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(amountPanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabel9, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(grossAmountLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabel10, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(taxAmountLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(jLabel11)
                    .addComponent(discountTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(discountAmountLabel, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.PREFERRED_SIZE, 21, javax.swing.GroupLayout.PREFERRED_SIZE)
                    .addComponent(discountValueTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(amountPanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(jLabel14, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                    .addComponent(netAmountLabel, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
                .addContainerGap())
        );

        jLabel22.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        jLabel22.setText("Payment:");

        paymentTypeComboBox.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        paymentTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(new String[] { "Cash", "Check", "Credit Card", "Bank Deposit", "Other" }));

        binding = org.jdesktop.beansbinding.Bindings.createAutoBinding(org.jdesktop.beansbinding.AutoBinding.UpdateStrategy.READ_WRITE, this, org.jdesktop.beansbinding.ELProperty.create("${invoice.invoicePaymentType}"), paymentTypeComboBox, org.jdesktop.beansbinding.BeanProperty.create("selectedItem"), "invoicePaymentTypeBinding");
        bindingGroup.addBinding(binding);

        paymentAmountFormattedTextField.setFormatterFactory(new javax.swing.text.DefaultFormatterFactory(new javax.swing.text.NumberFormatter(new java.text.DecimalFormat("#0.##"))));
        paymentAmountFormattedTextField.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        paymentAmountFormattedTextField.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyTyped(java.awt.event.KeyEvent evt) {
                paymentAmountFormattedTextFieldKeyTyped(evt);
            }
        });

        invoiceOptionsButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        invoiceOptionsButton.setText("Invoice Options");
        invoiceOptionsButton.setFocusable(false);

        previewInvoiceButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        previewInvoiceButton.setText("Preview");
        previewInvoiceButton.setFocusable(false);
        previewInvoiceButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                previewInvoiceButtonActionPerformed(evt);
            }
        });

        clearInvoiceButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        clearInvoiceButton.setText("Clear");
        clearInvoiceButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                clearInvoiceButtonActionPerformed(evt);
            }
        });

        createOrSaveInvoiceButton.setFont(new java.awt.Font("Tahoma", 0, 12)); // NOI18N
        createOrSaveInvoiceButton.setText("Create");
        createOrSaveInvoiceButton.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                createOrSaveInvoiceButtonActionPerformed(evt);
            }
        });

        javax.swing.GroupLayout invoicePanelLayout = new javax.swing.GroupLayout(invoicePanel);
        invoicePanel.setLayout(invoicePanelLayout);
        invoicePanelLayout.setHorizontalGroup(
            invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(invoicePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addComponent(jSeparator2, javax.swing.GroupLayout.Alignment.TRAILING)
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, invoicePanelLayout.createSequentialGroup()
                        .addComponent(invoiceOptionsButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(previewInvoiceButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addComponent(clearInvoiceButton)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addComponent(createOrSaveInvoiceButton))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, invoicePanelLayout.createSequentialGroup()
                        .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(invoicePanelLayout.createSequentialGroup()
                                .addComponent(addItemButton)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(removeItemButton)
                                .addGap(18, 18, 18)
                                .addComponent(moveUpItemButton, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
                                .addComponent(moveDownItemButton, javax.swing.GroupLayout.PREFERRED_SIZE, 40, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addGroup(invoicePanelLayout.createSequentialGroup()
                                .addComponent(publicNotesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addGap(18, 18, 18)
                                .addComponent(privateNotesPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                        .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addGroup(javax.swing.GroupLayout.Alignment.LEADING, invoicePanelLayout.createSequentialGroup()
                                .addComponent(jLabel22)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(paymentTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(paymentAmountFormattedTextField))
                            .addComponent(amountPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, invoicePanelLayout.createSequentialGroup()
                        .addGap(0, 0, Short.MAX_VALUE)
                        .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(jScrollPane2, javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(invoicePanelLayout.createSequentialGroup()
                                .addComponent(addressTabbedPane, javax.swing.GroupLayout.PREFERRED_SIZE, 443, javax.swing.GroupLayout.PREFERRED_SIZE)
                                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                                .addComponent(detailsTabbedPane, javax.swing.GroupLayout.PREFERRED_SIZE, 333, javax.swing.GroupLayout.PREFERRED_SIZE)))))
                .addContainerGap())
        );

        invoicePanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {clearInvoiceButton, createOrSaveInvoiceButton});

        invoicePanelLayout.linkSize(javax.swing.SwingConstants.HORIZONTAL, new java.awt.Component[] {addItemButton, removeItemButton});

        invoicePanelLayout.setVerticalGroup(
            invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(invoicePanelLayout.createSequentialGroup()
                .addContainerGap()
                .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING, false)
                    .addComponent(addressTabbedPane)
                    .addComponent(detailsTabbedPane))
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addComponent(jScrollPane2, javax.swing.GroupLayout.PREFERRED_SIZE, 156, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(13, 13, 13)
                .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                    .addGroup(invoicePanelLayout.createSequentialGroup()
                        .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
                            .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                                .addComponent(addItemButton)
                                .addComponent(removeItemButton)
                                .addComponent(moveUpItemButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                            .addComponent(moveDownItemButton, javax.swing.GroupLayout.PREFERRED_SIZE, 23, javax.swing.GroupLayout.PREFERRED_SIZE))
                        .addGap(18, 18, 18)
                        .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.TRAILING, false)
                            .addComponent(privateNotesPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
                            .addComponent(publicNotesPanel, javax.swing.GroupLayout.Alignment.LEADING, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)))
                    .addGroup(invoicePanelLayout.createSequentialGroup()
                        .addComponent(amountPanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                        .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                        .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                            .addComponent(jLabel22)
                            .addComponent(paymentTypeComboBox, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                            .addComponent(paymentAmountFormattedTextField, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE))))
                .addGap(11, 11, 11)
                .addComponent(jSeparator2, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
                .addGroup(invoicePanelLayout.createParallelGroup(javax.swing.GroupLayout.Alignment.CENTER)
                    .addComponent(invoiceOptionsButton)
                    .addComponent(createOrSaveInvoiceButton)
                    .addComponent(clearInvoiceButton)
                    .addComponent(previewInvoiceButton))
                .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
        );

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addComponent(invoicePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addGap(0, 0, Short.MAX_VALUE))
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addComponent(invoicePanel, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE)
        );

        bindingGroup.bind();
    }// </editor-fold>//GEN-END:initComponents

    private void billToAddressTextAreaFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_billToAddressTextAreaFocusGained
        if (billToAddressTextArea.getText().equals(DEFAULT_BILLTO_ADDRESS)) {
            billToAddressTextArea.setText("");
        }
        billToAddressTextArea.setForeground(Color.BLACK);
    }//GEN-LAST:event_billToAddressTextAreaFocusGained

    private void billToAddressTextAreaFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_billToAddressTextAreaFocusLost
        if (billToAddressTextArea.getText().equals("")) {
            billToAddressTextArea.setText(DEFAULT_BILLTO_ADDRESS);
            billToAddressTextArea.setForeground(Color.GRAY);
        }
    }//GEN-LAST:event_billToAddressTextAreaFocusLost

    private void billToAddressTextAreaKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_billToAddressTextAreaKeyReleased
        if(billingEqualsShippingCheckBox.isSelected()){
            shipToAddressTextArea.setText(billToAddressTextArea.getText());
        }
    }//GEN-LAST:event_billToAddressTextAreaKeyReleased

    private void shipToAddressTextAreaFocusGained(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_shipToAddressTextAreaFocusGained
        if (shipToAddressTextArea.getText().equals(DEFAULT_SHIPTO_ADDRESS)) {
            shipToAddressTextArea.setText("");
        }
        shipToAddressTextArea.setForeground(Color.BLACK);
    }//GEN-LAST:event_shipToAddressTextAreaFocusGained

    private void shipToAddressTextAreaFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_shipToAddressTextAreaFocusLost
        if (shipToAddressTextArea.getText().equals("") || shipToAddressTextArea.getText().equals(DEFAULT_SHIPTO_ADDRESS)) {
            shipToAddressTextArea.setText(DEFAULT_SHIPTO_ADDRESS);
            shipToAddressTextArea.setForeground(Color.GRAY);
        } else {
            shipToAddressTextArea.setForeground(Color.BLACK);
        }
    }//GEN-LAST:event_shipToAddressTextAreaFocusLost

    private void billToStateComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_billToStateComboBoxItemStateChanged
        String state = String.valueOf(billToStateComboBox.getSelectedItem());
        ArrayList cities = stateCityMapping.get(state);

        if (null==cities)
            billToCityComboBox.setModel(new DefaultComboBoxModel());
        else
            billToCityComboBox.setModel(new DefaultComboBoxModel(cities.toArray()));

        if(billingEqualsShippingCheckBox.isSelected()){
            shipToStateComboBox.setSelectedItem(billToStateComboBox.getSelectedItem());
            shipToCityComboBox.setSelectedItem(billToCityComboBox.getSelectedItem());
        }
    }//GEN-LAST:event_billToStateComboBoxItemStateChanged

    private void billToCityComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_billToCityComboBoxItemStateChanged
        if(billingEqualsShippingCheckBox.isSelected()){
            shipToStateComboBox.setSelectedItem(billToStateComboBox.getSelectedItem());
            shipToCityComboBox.setSelectedItem(billToCityComboBox.getSelectedItem());
        }
    }//GEN-LAST:event_billToCityComboBoxItemStateChanged

    private void shipToStateComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_shipToStateComboBoxItemStateChanged
        String state = String.valueOf(shipToStateComboBox.getSelectedItem());
        ArrayList cities = stateCityMapping.get(state);

        if (null==cities)
            shipToCityComboBox.setModel(new DefaultComboBoxModel());
        else
            shipToCityComboBox.setModel(new DefaultComboBoxModel(cities.toArray()));
    }//GEN-LAST:event_shipToStateComboBoxItemStateChanged

    private void customerComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_customerComboBoxItemStateChanged
        String customerName = String.valueOf(customerComboBox.getSelectedItem());
        
        Customer customer = customersMap.get(customerName);
        if(null!=customer) {
            populateCustomerDetailComponents(customer);
        }
    }//GEN-LAST:event_customerComboBoxItemStateChanged

    private void billToAddressTextAreaKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_billToAddressTextAreaKeyPressed
        CommonFunctions.textboxTABPolicy(evt);
    }//GEN-LAST:event_billToAddressTextAreaKeyPressed

    private void shipToAddressTextAreaKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_shipToAddressTextAreaKeyPressed
        CommonFunctions.textboxTABPolicy(evt);
    }//GEN-LAST:event_shipToAddressTextAreaKeyPressed

    private void billingEqualsShippingCheckBoxStateChanged(javax.swing.event.ChangeEvent evt) {//GEN-FIRST:event_billingEqualsShippingCheckBoxStateChanged
        if (billingEqualsShippingCheckBox.isSelected()) {
            setShipToAddressAsBillToAddress();
        } else {
            shipToAddressTextAreaFocusLost(null);
        }
        
        shipToAddressTextArea.setEnabled(!billingEqualsShippingCheckBox.isSelected());
        shipToStateComboBox.setEnabled(!billingEqualsShippingCheckBox.isSelected());
        shipToCityComboBox.setEnabled(!billingEqualsShippingCheckBox.isSelected());
    }//GEN-LAST:event_billingEqualsShippingCheckBoxStateChanged

    private void addEditCustomerButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addEditCustomerButtonActionPerformed
        String selectedCustomerName = customerComboBox.getEditor().getItem().toString();
        Customer selectedCustomer = customersMap.get(selectedCustomerName);
        if(null==selectedCustomer) {
            selectedCustomer = new Customer();
            selectedCustomer.setCustomerName(selectedCustomerName);
        } else {
            selectedCustomer = selectedCustomer.clone();
        }
        
        CustomersDialog customersDialog = new CustomersDialog(CommonFunctions.getParentJFrame(this), true, selectedCustomer);
        Customer customer = customersDialog.showDialog();
        if(null!=customer) {
            populateCustomers();
            customerComboBox.setSelectedItem(customer.getCustomerName());
        }
    }//GEN-LAST:event_addEditCustomerButtonActionPerformed

    private void clearInvoiceButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_clearInvoiceButtonActionPerformed
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        
        invoiceNoTextField.setText(InvoiceManager.getNextInvoiceNo());
        invoiceTypeComboBox.setSelectedItem(DEFAULT_INVOICE_TYPE);
        invoiceDateChooser.setDate(new Date());
        String currentUserName = UserManager.getFirstnameByUsername(SmartBooksUserSettings.USERNAME);
        salesPersonComboBox.setSelectedItem(currentUserName);
        poNoTextField.setText("");
        
        customerComboBox.setSelectedIndex(-1);
        billToAddressTextArea.setText(DEFAULT_BILLTO_ADDRESS);
        billToAddressTextArea.setForeground(Color.GRAY);
        billToStateComboBox.setSelectedItem(DEFAULT_BILLTO_STATE);
        // Above LOC will automatically make CityComboBox selected index to '0'
        // because it calls item state changed of the combobox
        billingEqualsShippingCheckBox.setSelected(true);
        billingEqualsShippingCheckBoxStateChanged(null);
        customerTaxComboBox.setSelectedItem(DEFAULT_CUSTOMER_TAX);
        
        initializeInvoiceLinesTable();
        
        publicNotesTextArea.setText("");
        privateNotesTextArea.setText("");
        
        grossAmountLabel.setText(df.format(0));
        taxAmountLabel.setText(df.format(0));
        discountTypeComboBox.setSelectedItem(DEFAULT_INVOICE_DISCOUNT_TYPE);
        discountValueTextField.setText("");
        discountAmountLabel.setText(df.format(0));
        netAmountLabel.setText(df.format(0));
        paymentTypeComboBox.setSelectedItem(DEFAULT_INVOICE_PAYMENT_TYPE);
        paymentAmountFormattedTextField.setText("");
    }//GEN-LAST:event_clearInvoiceButtonActionPerformed

    private void createOrSaveInvoiceButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_createOrSaveInvoiceButtonActionPerformed
        // To save data whenever a JTable cell still has focus and data still not edited and the button is clicked
        if (null!=invoiceLinesTable.getCellEditor()) {
            invoiceLinesTable.getCellEditor().stopCellEditing();
        }
        
        CommonMouseListener.hideException = false;
        
        try {
            if(null==invoiceDateChooser.getDate() && !((JTextField)invoiceDateChooser.getComponent(1)).getText().equals(DATE_PATTERN)) {
                MyException me = new MyException("", "Invalid Invoice Date");
                me.showBalloonTip((JComponent)invoiceDateChooser.getComponent(1));
                ((JComponent)invoiceDateChooser.getComponent(1)).requestFocus();
                return;
            }

            assignAdditionalInvoiceValues(createOrSaveInvoiceButton.getText());
            assignAdditionalInvoiceLinesValues(createOrSaveInvoiceButton.getText());

            boolean invoiceModified = false;
            switch (createOrSaveInvoiceButton.getText()) {
                case CREATE_BUTTON_TEXT:
                    invoiceModified = InvoiceManager.createInvoice(invoice, invoiceLinesList);
                    break;
                case SAVE_BUTTON_TEXT:
                    //invoiceModified = InvoiceManager.updateInvoice(selectedCustomer, editCustomerName);
                    break;
            }
            
            if(invoiceModified) {
                Toolkit.getDefaultToolkit().beep();
                
                switch (createOrSaveInvoiceButton.getText()) {
                    case CREATE_BUTTON_TEXT:
                        JOptionPane.showMessageDialog(this,"Invoice is created successfully !","SmartBooks - Success",JOptionPane.INFORMATION_MESSAGE);
                        break;
                    case SAVE_BUTTON_TEXT:
                        JOptionPane.showMessageDialog(this,"Invoice is updated successfully !","SmartBooks - Success",JOptionPane.INFORMATION_MESSAGE);
                        break;
                }
                
                setModifiedInvoiceInParent();
                CommonFunctions.dispose(this);
            } else {
                Toolkit.getDefaultToolkit().beep();
                JOptionPane.showMessageDialog(this,"There was some error in creating Invoice.\nKindly contact system administrator.","SmartBooks - Error",JOptionPane.ERROR_MESSAGE);
            }
        } catch (MyException me) {
            if(me.getComponentText().equalsIgnoreCase(INVOICE_NO)) {
                me.showBalloonTip(invoiceNoTextField);
                invoiceNoTextField.requestFocus();
            } else if(me.getComponentText().equalsIgnoreCase(INVOICE_DISCOUNT_VALUE)) {
                me.showBalloonTip(discountValueTextField);
                discountValueTextField.requestFocus();
            } else if(me.getComponentText().equalsIgnoreCase(INVOICE_PAYMENT_AMOUNT)) {
                me.showBalloonTip(paymentAmountFormattedTextField);
                paymentAmountFormattedTextField.requestFocus();
            } else if(me.getComponentText().equalsIgnoreCase(BILL_TO_STATE)) {
                me.showBalloonTip(billToStateComboBox);
                billToStateComboBox.requestFocus();
            } else if(me.getComponentText().equalsIgnoreCase(BILL_TO_CITY)) {
                me.showBalloonTip(billToCityComboBox);
                billToCityComboBox.requestFocus();
            } else if(me.getComponentText().equalsIgnoreCase(SHIP_TO_STATE)) {
                me.showBalloonTip(shipToStateComboBox);
                shipToStateComboBox.requestFocus();
            } else if(me.getComponentText().equalsIgnoreCase(SHIP_TO_CITY)) {
                me.showBalloonTip(shipToCityComboBox);
                shipToCityComboBox.requestFocus();
            }
        } catch (MandatoryFieldException ex) {
            Logger.getLogger(InvoicesPanel.class.getName()).log(Level.SEVERE, null, ex);
        }
    }//GEN-LAST:event_createOrSaveInvoiceButtonActionPerformed

    private void invoiceNoTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_invoiceNoTextFieldKeyTyped
        char c = evt.getKeyChar();  
        if (!(Character.isDigit(c) || (c == KeyEvent.VK_BACK_SPACE) || (c == KeyEvent.VK_DELETE))) {
            evt.consume();
        }
    }//GEN-LAST:event_invoiceNoTextFieldKeyTyped

    private void discountTypeComboBoxItemStateChanged(java.awt.event.ItemEvent evt) {//GEN-FIRST:event_discountTypeComboBoxItemStateChanged
        DecimalFormat df = new DecimalFormat("0.00");
        df.setMaximumFractionDigits(2);
        
        discountValueTextField.setText("");
        
        double discountAmount = 0;
        discountAmountLabel.setText(df.format(discountAmount));
        
        calculateNetAmount();
    }//GEN-LAST:event_discountTypeComboBoxItemStateChanged

    private void previewInvoiceButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_previewInvoiceButtonActionPerformed
        System.out.println(invoice);
    }//GEN-LAST:event_previewInvoiceButtonActionPerformed

    private void paymentAmountFormattedTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_paymentAmountFormattedTextFieldKeyTyped
        char c = evt.getKeyChar();  
        if (c=='-') {
            evt.consume();
        }
    }//GEN-LAST:event_paymentAmountFormattedTextFieldKeyTyped

    private void addItemButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_addItemButtonActionPerformed
        int rows = invoiceLinesTable.getRowCount();
        int i=0;
        
        for(i=0; i<rows; i++) {
            if(null==invoiceLinesTable.getValueAt(i, 0) || invoiceLinesTable.getValueAt(i, 0).equals("")) {
                invoiceLinesTable.setValueAt(i+1, i, 0);
                break;
            }
        }
        
        if(i>=rows) {
            DefaultTableModel model = (DefaultTableModel)invoiceLinesTable.getModel();
            model.addRow(new Object[8]);
            invoiceLinesTable.setValueAt(i+1, i, 0);
        }
        
        invoiceLinesTable.setRowSelectionInterval(i, i);
    }//GEN-LAST:event_addItemButtonActionPerformed

    private void removeItemButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_removeItemButtonActionPerformed
        int[] selectedRows = invoiceLinesTable.getSelectedRows();
        
        for(int i=selectedRows.length-1; i>=0; i--){
            DefaultTableModel model = (DefaultTableModel)invoiceLinesTable.getModel();
            model.removeRow(selectedRows[i]);
            if(invoiceLinesTable.getRowCount()<8) {
                model.addRow(new Object[8]);
            }
        }
        
        updateNoColumnOfTable();
    }//GEN-LAST:event_removeItemButtonActionPerformed

    private void moveUpItemButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveUpItemButtonActionPerformed
        try {
            DefaultTableModel model =  (DefaultTableModel)invoiceLinesTable.getModel();
            int[] rows = invoiceLinesTable.getSelectedRows();
            ArrayList<Integer> finalRows = new ArrayList<Integer>();
            
            for(int row : rows) {
                if(null!=invoiceLinesTable.getValueAt(row,0) && !invoiceLinesTable.getValueAt(row, 0).equals("")) {
                    finalRows.add(row);
                }
            }
            
            if(finalRows.size() > 0) {
                int[] finalSelectedRows = new int[finalRows.size()];
                for (int i=0; i < finalSelectedRows.length; i++)
                {
                    finalSelectedRows[i] = finalRows.get(i).intValue();
                }

                model.moveRow(finalSelectedRows[0],finalSelectedRows[finalSelectedRows.length-1],finalSelectedRows[0]-1);
                invoiceLinesTable.setRowSelectionInterval(finalSelectedRows[0]-1, finalSelectedRows[finalSelectedRows.length-1]-1);
            }
            
        } catch(ArrayIndexOutOfBoundsException ex) {
            //JOptionPane.showMessageDialog(this,"Unable to Move Up the first row !","SmartBooks - Warning",JOptionPane.WARNING_MESSAGE);
        }
        
        updateNoColumnOfTable();
    }//GEN-LAST:event_moveUpItemButtonActionPerformed

    private void moveDownItemButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_moveDownItemButtonActionPerformed
        try {
            DefaultTableModel model =  (DefaultTableModel)invoiceLinesTable.getModel();
            int[] rows = invoiceLinesTable.getSelectedRows();
            ArrayList<Integer> finalRows = new ArrayList<Integer>();
            
            int lastRow = -1;
            for(int i=0; i<invoiceLinesTable.getRowCount(); i++) {
                if(null==invoiceLinesTable.getValueAt(i,0) || invoiceLinesTable.getValueAt(i, 0).equals("")) {
                    lastRow = i-1;
                    break;
                }
            }
            for(int row : rows) {
                if(row==lastRow) {
                    throw new ArrayIndexOutOfBoundsException();
                }
                
                if(null!=invoiceLinesTable.getValueAt(row,0) && !invoiceLinesTable.getValueAt(row, 0).equals("")) {
                    finalRows.add(row);
                }
            }
            
            if(finalRows.size() > 0) {
                int[] finalSelectedRows = new int[finalRows.size()];
                for (int i=0; i < finalSelectedRows.length; i++)
                {
                    finalSelectedRows[i] = finalRows.get(i).intValue();
                }

                model.moveRow(finalSelectedRows[0],finalSelectedRows[finalSelectedRows.length-1],finalSelectedRows[0]+1);
                invoiceLinesTable.setRowSelectionInterval(finalSelectedRows[0]+1, finalSelectedRows[finalSelectedRows.length-1]+1);
            }
        } catch(ArrayIndexOutOfBoundsException ex) {
            //JOptionPane.showMessageDialog(this,"Unable to Move Down the last row !","SmartBooks - Warning",JOptionPane.WARNING_MESSAGE);
        }
        
        updateNoColumnOfTable();
    }//GEN-LAST:event_moveDownItemButtonActionPerformed

    private void discountValueTextFieldKeyTyped(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_discountValueTextFieldKeyTyped
        CommonFunctions.addFloatPatternKeyTypedListener(evt);
    }//GEN-LAST:event_discountValueTextFieldKeyTyped

    private void discountValueTextFieldKeyReleased(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_discountValueTextFieldKeyReleased
        calculateDiscountAmount();
    }//GEN-LAST:event_discountValueTextFieldKeyReleased

    private void discountValueTextFieldFocusLost(java.awt.event.FocusEvent evt) {//GEN-FIRST:event_discountValueTextFieldFocusLost
        /*double discountValue = 0;
        
        if(null!=discountValueTextField.getText() && !discountValueTextField.getText().equals("")) {
            discountValue = Double.parseDouble(discountValueTextField.getText());
        }
        
        if(discountTypeComboBox.getSelectedItem().equals("%")) {
            if(discountValue>100) {
                new MyException(INVOICE_DISCOUNT_VALUE, "Discount cannot be greater than 100").showBalloonTip(discountValueTextField);
                discountValueTextField.requestFocus();
                discountValueTextField.selectAll();
            }
        }
        
        if(discountTypeComboBox.getSelectedItem().equals("-")) {
            double grossAmount = Double.parseDouble(grossAmountLabel.getText());
            double taxAmount = Double.parseDouble(taxAmountLabel.getText());
            
            if(discountValue>(grossAmount+taxAmount)) {
                new MyException(INVOICE_DISCOUNT_VALUE, "Discount value cannot be greater than Gross Amount + Tax Amount").showBalloonTip(discountValueTextField);
                discountValueTextField.requestFocus();
                discountValueTextField.selectAll();
            }
        }*/
    }//GEN-LAST:event_discountValueTextFieldFocusLost

    private void publicNotesTextAreaKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_publicNotesTextAreaKeyPressed
        CommonFunctions.textboxTABPolicy(evt);
    }//GEN-LAST:event_publicNotesTextAreaKeyPressed

    private void privateNotesTextAreaKeyPressed(java.awt.event.KeyEvent evt) {//GEN-FIRST:event_privateNotesTextAreaKeyPressed
        CommonFunctions.textboxTABPolicy(evt);
    }//GEN-LAST:event_privateNotesTextAreaKeyPressed

    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JButton addEditCustomerButton;
    private javax.swing.JButton addItemButton;
    private javax.swing.JTabbedPane addressTabbedPane;
    private javax.swing.JPanel amountPanel;
    private javax.swing.JTextArea billToAddressTextArea;
    private javax.swing.JComboBox billToCityComboBox;
    private javax.swing.JComboBox billToStateComboBox;
    private javax.swing.JCheckBox billingEqualsShippingCheckBox;
    private javax.swing.JButton clearInvoiceButton;
    private javax.swing.JButton createOrSaveInvoiceButton;
    private javax.swing.JComboBox customerComboBox;
    private javax.swing.JComboBox customerTaxComboBox;
    private javax.swing.JTabbedPane detailsTabbedPane;
    private javax.swing.JLabel discountAmountLabel;
    private javax.swing.JComboBox discountTypeComboBox;
    private javax.swing.JTextField discountValueTextField;
    private javax.swing.JLabel grossAmountLabel;
    private com.toedter.calendar.JDateChooser invoiceDateChooser;
    private javax.swing.JTable invoiceLinesTable;
    private javax.swing.JTextField invoiceNoTextField;
    private javax.swing.JButton invoiceOptionsButton;
    private javax.swing.JPanel invoicePanel;
    private javax.swing.JComboBox invoiceTypeComboBox;
    private javax.swing.JLabel jLabel1;
    private javax.swing.JLabel jLabel10;
    private javax.swing.JLabel jLabel11;
    private javax.swing.JLabel jLabel14;
    private javax.swing.JLabel jLabel16;
    private javax.swing.JLabel jLabel2;
    private javax.swing.JLabel jLabel22;
    private javax.swing.JLabel jLabel23;
    private javax.swing.JLabel jLabel24;
    private javax.swing.JLabel jLabel25;
    private javax.swing.JLabel jLabel26;
    private javax.swing.JLabel jLabel3;
    private javax.swing.JLabel jLabel4;
    private javax.swing.JLabel jLabel5;
    private javax.swing.JLabel jLabel6;
    private javax.swing.JLabel jLabel7;
    private javax.swing.JLabel jLabel8;
    private javax.swing.JLabel jLabel9;
    private javax.swing.JPanel jPanel2;
    private javax.swing.JPanel jPanel3;
    private javax.swing.JPanel jPanel4;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JScrollPane jScrollPane2;
    private javax.swing.JScrollPane jScrollPane3;
    private javax.swing.JScrollPane jScrollPane4;
    private javax.swing.JScrollPane jScrollPane5;
    private javax.swing.JSeparator jSeparator1;
    private javax.swing.JSeparator jSeparator2;
    private javax.swing.JButton moveDownItemButton;
    private javax.swing.JButton moveUpItemButton;
    private javax.swing.JLabel netAmountLabel;
    private javax.swing.JFormattedTextField paymentAmountFormattedTextField;
    private javax.swing.JComboBox paymentTypeComboBox;
    private javax.swing.JTextField poNoTextField;
    private javax.swing.JButton previewInvoiceButton;
    private javax.swing.JPanel privateNotesPanel;
    private javax.swing.JTextArea privateNotesTextArea;
    private javax.swing.JPanel publicNotesPanel;
    private javax.swing.JTextArea publicNotesTextArea;
    private javax.swing.JButton removeItemButton;
    private javax.swing.JComboBox salesPersonComboBox;
    private javax.swing.JTextArea shipToAddressTextArea;
    private javax.swing.JComboBox shipToCityComboBox;
    private javax.swing.JComboBox shipToStateComboBox;
    private javax.swing.JLabel taxAmountLabel;
    private org.jdesktop.beansbinding.BindingGroup bindingGroup;
    // End of variables declaration//GEN-END:variables
    
    KeyListener keyListener = new KeyListener() {

        @Override
        public void keyTyped(KeyEvent e) {}

        @Override
        public void keyPressed(KeyEvent e) {}

        @Override
        public void keyReleased(KeyEvent e) {
            if(e.getKeyCode() == KeyEvent.VK_ENTER) { 
                createOrSaveInvoiceButtonActionPerformed(null);
            }
        }
    };
}